package cn.tpshion.vm.handler;

import cn.tpshion.vm.common.constant.MsgType;
import cn.tpshion.vm.domain.support.MsgData;
import cn.tpshion.vm.domain.support.NodeContext;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
@Component
public class LocalCommandHandler {

    @Resource
    private SSEHandle sseHandle;

    @Resource
    private ThreadPoolTaskExecutor sshExecutor;

    public int exec(String command, NodeContext context) throws Exception{
        return exec(command, null, context);
    }

    public int exec(String command, String workspace, NodeContext context) throws Exception{
        if(StringUtils.isBlank(command)){
            return 1;
        }

        List<String> commandList = new ArrayList<>();
        commandList.add("/bin/sh");
        commandList.add("-c");
        commandList.add(command);

        log.info("LocalCommandHandle commandList:{}", commandList);
        sseHandle.sendMessage(context, MsgData.of(MsgType.INFO, commandList.toString()));
        ProcessBuilder processBuilder = new ProcessBuilder(commandList);
        if(StringUtils.isNoneBlank(workspace)){
            processBuilder.directory(new File(workspace));
        }

        Process process = processBuilder.start();
        try{
            readStream(process.getInputStream(), context);
            readErrorStream(process.getErrorStream(), context);
            int exitCode = process.waitFor();
            log.info("LocalCommandHandle exec exitCode:{}", exitCode);
            sseHandle.sendMessage(context, MsgData.of(MsgType.INFO, "命令执行结束 exitCode:" + exitCode));
            return exitCode;
        }finally {
            process.destroy();
        }
    }

    public void stop(String dockerId, NodeContext context) throws Exception {
        exec("docker stop " + dockerId, context);
    }

    private void readStream(final InputStream stream, NodeContext context) {
        if(Objects.isNull(stream)){
            return;
        }
        sshExecutor.execute(() -> {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))){
                String line;
                while ((line = reader.readLine()) != null) {
                    log.info("readStream exec log:{}", line);
                    if(StringUtils.isNoneBlank(line)){
                        sseHandle.sendMessage(context, MsgData.of(MsgType.INFO, line));
                    }
                }
            }catch (Exception e){
                log.error("readStream error:{}", e.getMessage(), e);
            }
        });
    }

    private void readErrorStream(final InputStream stream, NodeContext context){
        if(Objects.isNull(stream)){
            return;
        }
        sshExecutor.execute(() -> {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))){
                String line;
                while ((line = reader.readLine()) != null) {
                    log.info("readErrorStream exec log:{}", line);
                    if(StringUtils.isNoneBlank(line)){
                        sseHandle.sendMessage(context, MsgData.of(MsgType.INFO, line));
                    }
                }
            }catch (Exception e){
                log.error("readErrorStream error:{}", e.getMessage(), e);
            }
        });
    }
}
